/**
 * 日期工具类
 * 提供日期格式化、解析和计算功能
 */
export default class DateUtil {
  /** 默认日期格式 */
  public static readonly YYYY = "yyyy";
  public static readonly YYYY_MM = "yyyy-MM";
  public static readonly YYYY_MM_DD = "yyyy-MM-dd";
  public static readonly YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
  public static readonly YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

  /** 支持解析的日期格式 */
  private static readonly parsePatterns = [
    "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
    "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
    "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"
  ];

  /**
   * 获取当前Date型日期
   * 
   * @returns Date 当前日期
   */
  public static getNowDate(): Date {
    return new Date();
  }

  /**
   * 获取当前日期, 默认格式为yyyy-MM-dd
   * 
   * @returns 格式化的日期字符串
   */
  public static getDate(): string {
    return this.formatDate(this.YYYY_MM_DD);
  }

  /**
   * 获取当前日期时间 格式为yyyy-MM-dd HH:mm:ss
   * 
   * @returns 格式化的日期时间字符串
   */
  public static getTime(): string {
    return this.formatDate(this.YYYY_MM_DD_HH_MM_SS);
  }

  /**
   * 获取当前日期时间 格式为yyyyMMddHHmmss
   * 
   * @returns 格式化的日期时间字符串
   */
  public static dateTimeNow(): string {
    return this.formatDate(this.YYYYMMDDHHMMSS);
  }

  /**
   * 获取当前日期时间，按照指定格式
   * 
   * @param format 日期格式
   * @returns 格式化后的日期字符串
   */
  public static formatDate(format: string): string {
    return this.parseDateToStr(format, new Date());
  }

  /**
   * 将日期格式化为yyyy-MM-dd格式字符串
   * 
   * @param date 日期
   * @returns 格式化后的日期字符串
   */
  public static formatDateToYMD(date: Date): string {
    return this.parseDateToStr(this.YYYY_MM_DD, date);
  }

  /**
   * 将日期转换为指定格式的字符串
   * 
   * @param format 格式
   * @param date 日期
   * @returns 格式化后的日期字符串
   */
  public static parseDateToStr(format: string, date: Date): string {
    const year = date.getFullYear().toString();
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    const day = date.getDate().toString().padStart(2, '0');
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    const seconds = date.getSeconds().toString().padStart(2, '0');

    return format
      .replace(/yyyy/g, year)
      .replace(/MM/g, month)
      .replace(/dd/g, day)
      .replace(/HH/g, hours)
      .replace(/mm/g, minutes)
      .replace(/ss/g, seconds);
  }

  /**
   * 通过多种格式解析日期字符串为日期对象
   * 
   * @param str 日期字符串
   * @returns 日期对象，解析失败返回null
   */
  public static parseDate(str: string | null | undefined): Date | null {
    if (str === null || str === undefined) {
      return null;
    }
    
    // 尝试以ISO格式直接解析
    const dateObj = new Date(str);
    if (!isNaN(dateObj.getTime())) {
      return dateObj;
    }
    
    // 尝试通过多种格式解析
    for (const pattern of this.parsePatterns) {
      try {
        // 简化处理，只支持常见格式
        if (pattern === 'yyyy-MM-dd') {
          const parts = str.split('-');
          if (parts.length === 3) {
            return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
          }
        } else if (pattern === 'yyyy-MM-dd HH:mm:ss') {
          const dateTimeParts = str.split(' ');
          if (dateTimeParts.length === 2) {
            const dateParts = dateTimeParts[0].split('-');
            const timeParts = dateTimeParts[1].split(':');
            if (dateParts.length === 3 && timeParts.length === 3) {
              return new Date(
                parseInt(dateParts[0]), parseInt(dateParts[1]) - 1, parseInt(dateParts[2]),
                parseInt(timeParts[0]), parseInt(timeParts[1]), parseInt(timeParts[2])
              );
            }
          }
        } else if (pattern === 'yyyy/MM/dd') {
          const parts = str.split('/');
          if (parts.length === 3) {
            return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
          }
        } else if (pattern === 'yyyy.MM.dd') {
          const parts = str.split('.');
          if (parts.length === 3) {
            return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
          }
        }
      } catch (e) {
        // 忽略解析错误，尝试下一种格式
        continue;
      }
    }
    
    return null;
  }

  /**
   * 获取当前日期的路径格式，即年/月/日 如2022/08/08
   */
  public static datePath(): string {
    const now = new Date();
    return this.parseDateToStr("yyyy/MM/dd", now);
  }

  /**
   * 获取当前日期的数字格式，即年月日 如20220808
   */
  public static getFormattedDateNumber(): string {
    const now = new Date();
    return this.parseDateToStr("yyyyMMdd", now);
  }

  /**
   * 计算两个日期之间相差的天数
   * 
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 相差的天数
   */
  public static differentDaysByMillisecond(date1: Date, date2: Date): number {
    return Math.abs(Math.floor((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
  }

  /**
   * 增加天数
   * 
   * @param date 日期
   * @param days 天数
   * @returns 增加后的日期
   */
  public static addDays(date: Date, days: number): Date {
    const result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
  }

  /**
   * 增加月份
   * 
   * @param date 日期
   * @param months 月数
   * @returns 增加后的日期
   */
  public static addMonths(date: Date, months: number): Date {
    const result = new Date(date);
    result.setMonth(result.getMonth() + months);
    return result;
  }

  /**
   * 增加年份
   * 
   * @param date 日期
   * @param years 年数
   * @returns 增加后的日期
   */
  public static addYears(date: Date, years: number): Date {
    const result = new Date(date);
    result.setFullYear(result.getFullYear() + years);
    return result;
  }

  /**
   * 获取某月的天数
   * 
   * @param year 年份
   * @param month 月份（1-12）
   * @returns 该月天数
   */
  public static getDaysInMonth(year: number, month: number): number {
    return new Date(year, month, 0).getDate();
  }

  /**
   * 比较两个日期大小
   * 
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 如果date1大于date2返回1，小于返回-1，相等返回0
   */
  public static compare(date1: Date, date2: Date): number {
    const time1 = date1.getTime();
    const time2 = date2.getTime();
    
    if (time1 > time2) {
      return 1;
    } else if (time1 < time2) {
      return -1;
    } else {
      return 0;
    }
  }

  /**
   * 判断是否是工作日（周一至周五）
   * 
   * @param date 日期
   * @returns 是否是工作日
   */
  public static isWeekday(date: Date): boolean {
    const day = date.getDay();
    return day !== 0 && day !== 6;
  }

  /**
   * 判断是否是周末（周六和周日）
   * 
   * @param date 日期
   * @returns 是否是周末
   */
  public static isWeekend(date: Date): boolean {
    const day = date.getDay();
    return day === 0 || day === 6;
  }
} 